package com.gurumades.triggers.client;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class TriggerRegistryImpl implements TriggerRegistry {

	HashMap<Object, List<Registration>> TriggersToTriggerables = new HashMap<Object, List<Registration>>();
	HashMap<Trigerable, List<Registration>> trigerablesToTriggers = new HashMap<Trigerable, List<Registration>>();

	HashMap<Trigger, Object> triggersvalues = new HashMap<Trigger, Object>();

	@Override
	public void register(Trigerable toTrigger, Trigger source, Object value,
			TriggerChangeComparator comparator, boolean whatToDo) {
		List<Registration> list = TriggersToTriggerables.get(source);
		if (list == null) {
			list = new ArrayList<Registration>();
			TriggersToTriggerables.put(source, list);
		}
		list.add(new Registration(comparator, value, toTrigger, source,
				whatToDo));

		list = trigerablesToTriggers.get(toTrigger);
		if (list == null) {
			list = new ArrayList<Registration>();
			trigerablesToTriggers.put(toTrigger, list);
		}
		list.add(new Registration(comparator, value, toTrigger, source,
				whatToDo));
	}

	@Override
	public Map<Trigerable, Boolean> getMatchings(Object source, Object value) {
		Map<Trigerable, List<Boolean>> voteMap = new HashMap<Trigerable, List<Boolean>>();

		Map<Trigerable, Boolean> returnVal = new HashMap<Trigerable, Boolean>();

		List<Registration> triggerables = TriggersToTriggerables.get(source);
		if (triggerables == null) {
			triggerables = new ArrayList<TriggerRegistryImpl.Registration>();
		}
		List<Trigerable> triggeredItems = new ArrayList<Trigerable>();

		for (Registration registration : triggerables) {
			triggeredItems.add(registration.getTriggerable());

		}

		for (Trigerable trigerable : triggeredItems) {
			voteMap.put(trigerable, new ArrayList<Boolean>());
		}

		for (Trigerable trigerable : triggeredItems) {
			List<Registration> triggers = trigerablesToTriggers.get(trigerable);

			if (triggers == null) {
				triggers = new ArrayList<TriggerRegistryImpl.Registration>();
			}

			for (Registration registration : triggers) {
				List<Boolean> list = voteMap.get(trigerable);
				TriggerChangeComparator comparator = registration
						.getComparator();
				Trigger trigger = registration.getSource();
				Object lastKNownValue = triggersvalues.get(trigger);

				Boolean res = comparator.compareValues(registration.getValue(),
						lastKNownValue);

				if (res) {
					list.add(true);
				}else{
					list.add(false);
				}

			}
		}

		for (Trigerable trigerable : voteMap.keySet()) {
			if (!voteMap.get(trigerable).contains(Boolean.FALSE)) {
				returnVal.put(trigerable, true);
			}else {
				returnVal.put(trigerable, false);
			}
		}

		return returnVal;
	}

	public class Registration {

		@Override
		public String toString() {
			return "Registration [value=" + value + ", toTrigger=" + toTrigger
					+ ", source=" + source + ", whatTo=" + whatTo + "]";
		}

		private TriggerChangeComparator comparator;
		private Object value;
		private Trigerable toTrigger;
		private Trigger source;
		private boolean whatTo;

		public Registration(TriggerChangeComparator comparator, Object value,
				Trigerable toTrigger, Trigger source, boolean whatTo) {
			super();
			this.comparator = comparator;
			this.value = value;
			this.toTrigger = toTrigger;
			this.source = source;
			this.whatTo = whatTo;
		}

		public boolean whatToTrigger() {
			return whatTo;
		}

		public Trigerable getTriggerable() {
			return toTrigger;
		}

		public Trigger getSource() {
			return source;
		}

		public TriggerChangeComparator getComparator() {
			return comparator;
		}

		public Object getValue() {
			return value;
		}

	}

	@Override
	public void reportEvent(TriggerChangeEvent triggerChange) {
		triggersvalues.put(triggerChange.getSource(), triggerChange.getValue());
	}

	@Override
	public void reset() {
		this.trigerablesToTriggers.clear();
		this.triggersvalues.clear();
		this.TriggersToTriggerables.clear();
	}

}
